/**
 * 处理条件规则
 * 条件隐藏、条件样式、条件只读、条件必填
 */
import { fieldFilter, groupFilter } from "../utils/filter";
import keys from "lodash/keys";
import setRuleResult from "./setRuleResult";
import eventBus from "../eventBus";
import { mergecalculateFormData } from "../../../apis/mergeFormData";
import set from "lodash/set";
import get from "lodash/get";
import cloneDeep from "lodash/cloneDeep";
import calculateExpression, { operator } from "../../../expression/arithmetic"; //规则和计算
import { updateField } from "../context/metadata-context";
import { formatNumber, getBackFillAreaValue } from "../utils";
let parser = calculateExpression.parser;
let calculator = calculateExpression.calculator();

/**
 * 
 * @param {*} expression 
 * @returns {boolean} - false 存在聚合函数， true 不存在聚合函数
 */
function getIscalculate(expression) {
  // onlyforplansystem才需要关联字段发生改变才请求
  var exclude = ["sum", "onlyforplansystem", "min", "max"];
  var str = expression.toLowerCase();
  var isCalculate = false;
  for (var i = 0; i < exclude.length; i++) {
    if (str.indexOf(exclude[i]) > -1) {
      isCalculate = true;
    }
  }
  return !isCalculate;
}

export function applyRule(tplData) {
  //把规则字符串暂存到rules
  tplData.rules = {};
  (tplData.form?.form_rules || []).forEach((rule) => {
    tplData.rules[rule.id] = JSON.stringify(rule.rule || "");
  });
  tplData.form.form_meta_data.groups.filter(groupFilter).forEach((group) => {
    //分组规则
    let groupRules = group.rules;

    if (groupRules) {
      let groupHiddenRules = groupRules.hidden?.rules;
      if (groupHiddenRules && groupHiddenRules.length > 0) {
        setRuleResult({
          tb_code: "main", //所在分组code 主表为main
          type: "init",
          rules: groupRules.hidden, //当前字段的隐藏规则
          form_rules: tplData.form.form_rules, //当前表单的所有规则
          form_data: tplData.calculateFormData, //表单数据
          callBack: function (rst_value) {
            if (rst_value === true) {
              group.isHidden = true;
            }
            // cell.isHidden = rst_value; //给单元格绑定条件隐藏属性
          },
        });

        groupHiddenRules.forEach((rule) => {
          //注册规则
          eventBus.subscribe(`rule.${rule}`, () => {
            setRuleResult({
              tb_code: "main", //所在分组code 主表为main
              type: "init",
              rules: groupRules.hidden, //当前字段的隐藏规则
              form_rules: tplData.form.form_rules, //当前表单的所有规则
              form_data: mergecalculateFormData(tplData), //表单数据
              callBack: function (rst_value) {
                if (group.isHidden !== rst_value) {
                  //如果有变化就更新
                  group.isHidden = rst_value; //给单元格绑定条件隐藏属性
                  eventBus.publish(`group.update.${group.id || group.code}`);
                }
              },
            });
          });
        });
      }
    }

    //是否是子表
    let isSubTable = group.isSubTable;
    if (isSubTable === true) {
      //子表
      let subTableRows = tplData.form.form_data?.children?.[group.code];
      if(!subTableRows){//如果数据源里面没有包含子表数据，前端做兼容给一个默认的空数组
        subTableRows = [];
        set(tplData, "form.form_data.children." + group.code, subTableRows);
      }

      //fixme: 不依赖当前子表时，直接过滤掉列隐藏设置满足Hidden条件的
      let fields = group.fields.filter(fieldFilter);
      fields.forEach((cellData, index) => {
        if (cellData.isHiddenRows === undefined) cellData.isHiddenRows = [];
        if (cellData.isRequiredRows === undefined) cellData.isRequiredRows = [];
        if (cellData.contentStyles === undefined) cellData.contentStyles = [];
        let rules = cellData.designProps?.rules;

        if (rules) {
          let hiddenRules = rules.hidden?.rules;

          let requiredRules = rules.required?.rules;
          //1.找到所有的content样式规则
          let allContentStyles = rules.style?.filter((s) => s.target === "content") || [];

          let linkHideRules = cellData.designProps?.rules?.hiddenLink; //超链接隐藏条件

          function applyContentRule(rowIndex, mergedCalculateFormData) {
            let hasContentStyle = false;
            //之前的逻辑是把最后一个成功的规则Apply
            for (let index = allContentStyles.length - 1; index >= 0; index--) {
              if (hasContentStyle === true) break; //第一个满足条件的Apply样式规则
              const element = allContentStyles[index];
              setRuleResult({
                tb_code: group.code, //所在分组code 主表为main
                type: "init",
                rules: { rules: [element.id] }, //当前字段的样式规则
                form_rules: tplData.form.form_rules, //当前表单的所有规则
                form_data: mergedCalculateFormData, //表单数据
                row_i: rowIndex,
                callBack: function (rst_value) {
                  if (rst_value === true) {
                    hasContentStyle = true;
                    cellData.contentStyles[rowIndex] = element.style; //给单元格绑定条件隐藏属性
                  }
                },
              });
            }
            if (hasContentStyle === false) {
              delete cellData.contentStyles[rowIndex];
            }
          }

          function applyLinkRule(rowIndex, mergedCalculateFormData) {
            if (cellData.linkHidden === undefined) cellData.linkHidden = {}; //超链接隐藏结果
            let hideResult = []; //当前超链接字段的所有隐藏结果
            linkHideRules.forEach(function (linkHideRule, index) {
              //遍历超链接条件
              if (linkHideRule.linkName && hideResult.length !== undefined) {
                //如果超链接条件存在linkName
                hideResult = {}; //把hideResult转成对象
              }
              if (linkHideRule.id !== undefined) {
                setRuleResult({
                  tb_code: group.code, //所在分组code 主表为main
                  type: "init",
                  rules: linkHideRule.id, //当前字段的隐藏规则
                  form_rules: tplData.form.form_rules, //当前表单的所有规则
                  form_data: mergedCalculateFormData, //表单数据
                  row_i: rowIndex,
                  callBack: function (rst_value) {
                    if (linkHideRule.linkName) {
                      //如果超链接条件存在linkName
                      hideResult[linkHideRule.linkName] = rst_value; //当前条件的链接名称
                    } else {
                      //兼容历史数据，没有linkName，直接存结果
                      hideResult.push(rst_value);
                    }
                  },
                }); //设置列隐藏
                cellData.linkHidden[rowIndex] = hideResult;
              }
            });
          }
          subTableRows.forEach((row, rowIndex) => {
            //是否有隐藏规则

            if (hiddenRules && hiddenRules.length > 0) {
              setRuleResult({
                tb_code: group.code, //所在分组code 主表为main
                type: "init",
                rules: rules.hidden, //当前字段的隐藏规则
                form_rules: tplData.form.form_rules, //当前表单的所有规则
                form_data: tplData.calculateFormData, //表单数据
                row_i: rowIndex,
                callBack: function (rst_value) {
                  if (rst_value === true) cellData.isHiddenRows[rowIndex] = rst_value; //给当前列记录隐藏属性，只有隐藏时才记录
                },
              }); //设置列隐藏
            }

            if (requiredRules && requiredRules.length > 0) {
              setRuleResult({
                tb_code: group.code, //所在分组code 主表为main
                type: "init",
                rules: rules.required, //当前字段的隐藏规则
                form_rules: tplData.form.form_rules, //当前表单的所有规则
                form_data: tplData.calculateFormData, //表单数据
                row_i: rowIndex,
                callBack: function (rst_value) {
                  if (rst_value === true) cellData.isRequiredRows[rowIndex] = rst_value; //给当前列记录隐藏属性，只有隐藏时才记录
                },
              }); //设置列隐藏
            }

            if (rules.style?.length > 0) {
              //有样式规则需要应用
              //content样式
              applyContentRule(rowIndex, tplData.calculateFormData);
            }

            //超链接隐藏

            if (linkHideRules) {
              applyLinkRule(rowIndex, tplData.calculateFormData);
            }
          });

          hiddenRules?.forEach((rule) => {
            //注册隐藏规则
            eventBus.subscribe(`rule.${rule}`, (rowIndex) => {
              let mergedCalculateFormData = mergecalculateFormData(tplData);
              //主表触发
              if (rowIndex === undefined) {
                let isChanged = false;
                subTableRows.forEach((row, rowIndex) => {
                  setRuleResult({
                    tb_code: group.code, //所在分组code 主表为main
                    type: "init",
                    rules: rules.hidden, //当前字段的隐藏规则
                    form_rules: tplData.form.form_rules, //当前表单的所有规则
                    form_data: mergedCalculateFormData, //表单数据
                    row_i: rowIndex,
                    callBack: function (rst_value) {
                      if (cellData.isHiddenRows[rowIndex] !== rst_value) {
                        //如果有变化就更新
                        if (rst_value === true) cellData.isHiddenRows[rowIndex] = rst_value; //给单元格绑定条件隐藏属性
                        else {
                          delete cellData.isHiddenRows[rowIndex];
                        }
                        isChanged = true;
                      }
                    },
                  });
                });
                if (isChanged) eventBus.publish(`group.update.${group.code}`);
              } //子表触发
              else {
                setRuleResult({
                  tb_code: group.code, //所在分组code 主表为main
                  type: "init",
                  rules: rules.hidden, //当前字段的隐藏规则
                  form_rules: tplData.form.form_rules, //当前表单的所有规则
                  form_data: mergedCalculateFormData, //表单数据
                  row_i: rowIndex,
                  callBack: function (rst_value) {
                    if (cellData.isHiddenRows[rowIndex] !== rst_value) {
                      if (rst_value === true) cellData.isHiddenRows[rowIndex] = rst_value; //给单元格绑定条件隐藏属性
                      else {
                        delete cellData.isHiddenRows[rowIndex];
                        delete cellData.isHidden;
                      }
                      eventBus.publish(`group.update.${group.code}`);
                    }
                  },
                });
              }
            });
          });

          requiredRules?.forEach((rule) => {
            //注册隐藏规则
            eventBus.subscribe(`rule.${rule}`, (rowIndex) => {
              let mergedCalculateFormData = mergecalculateFormData(tplData);
              //主表触发
              if (rowIndex === undefined) {
                let isChanged = false;
                subTableRows.forEach((row, rowIndex) => {
                  setRuleResult({
                    tb_code: group.code, //所在分组code 主表为main
                    type: "init",
                    rules: rules.required, //当前字段的隐藏规则
                    form_rules: tplData.form.form_rules, //当前表单的所有规则
                    form_data: mergedCalculateFormData, //表单数据
                    row_i: rowIndex,
                    callBack: function (rst_value) {
                      if (cellData.isRequiredRows[rowIndex] !== rst_value) {
                        //如果有变化就更新
                        if (rst_value === true) cellData.isRequiredRows[rowIndex] = rst_value; //给单元格绑定条件隐藏属性
                        else {
                          delete cellData.isRequiredRows[rowIndex];
                        }
                        isChanged = true;
                      }
                    },
                  });
                });
                if (isChanged) eventBus.publish(`group.update.${group.code}`);
              } //子表触发
              else {
                setRuleResult({
                  tb_code: group.code, //所在分组code 主表为main
                  type: "init",
                  rules: rules.required, //当前字段的隐藏规则
                  form_rules: tplData.form.form_rules, //当前表单的所有规则
                  form_data: mergedCalculateFormData, //表单数据
                  row_i: rowIndex,
                  callBack: function (rst_value) {
                    if (cellData.isRequiredRows[rowIndex] !== rst_value) {
                      if (rst_value === true) cellData.isRequiredRows[rowIndex] = rst_value; //给单元格绑定条件隐藏属性
                      else {
                        delete cellData.isRequiredRows[rowIndex];
                      }
                      eventBus.publish(`group.update.${group.code}`);
                    }
                  },
                });
              }
            });
          });

          allContentStyles.forEach((element) => {
            eventBus.subscribe(`rule.${element.id}`, (rowIndex) => {
              let mergedCalculateFormData = mergecalculateFormData(tplData);

              //主表触发
              if (rowIndex === undefined) {
                subTableRows.forEach((row, rowIndex) => {
                  applyContentRule(rowIndex, mergedCalculateFormData);
                });
                eventBus.publish(`group.update.${group.code}`);
              } //子表触发
              else {
                applyContentRule(rowIndex, mergedCalculateFormData);
                eventBus.publish(`group.update.${group.code}`);
              }
            });
          });

          linkHideRules?.forEach((element) => {
            eventBus.subscribe(`rule.${element.id}`, (rowIndex) => {
              let mergedCalculateFormData = mergecalculateFormData(tplData);

              //主表触发
              if (rowIndex === undefined) {
                subTableRows.forEach((row, rowIndex) => {
                  applyLinkRule(rowIndex, mergedCalculateFormData);
                });
                eventBus.publish(`group.update.${group.code}`);
              } //子表触发
              else {
                applyLinkRule(rowIndex, mergedCalculateFormData);
                eventBus.publish(`group.update.${group.code}`);
              }
            });
          });
        }
      });
      // });

      //处理整列隐藏
      let totalRows = subTableRows.length; //子表数据总行数
      for (let index = 0; index < fields.length; index++) {
        let field = fields[index];
        //如果设计器给的标识is_show===false,需要隐藏当前列
        //子表的is_show被放到了group.columns里面, fixme: 后面重构
        if (group.columns?.find((c) => c.code == field.code && c.is_show === false)) {
          field.isHidden = true;
        }

        if (totalRows !== 0 && totalRows === Object.keys(field.isHiddenRows).length) {
          //如果当前列隐藏的行数 == 子表数据总行数
          field.isHidden = true; //整列隐藏
        }
      }
    } else {
      //主表
      group?.rows?.forEach((row) => {
        //主表计算规则
        row?.cols?.forEach((cell) => {
          let cellData = cell?.data?.[0];
          //如果设计器给的标识is_show===false,需要隐藏cell
          if (cellData?.is_show === false) {
            cell.isHidden = true;
          }
          let code = cellData?.code;
          if (code) {
            //有配置字段
            let rules = cellData?.designProps?.rules;
            if (rules) {
              //是否有隐藏规则
              let hiddenRules = rules.hidden?.rules;
              if (hiddenRules && hiddenRules.length > 0) {
                setRuleResult({
                  tb_code: "main", //所在分组code 主表为main
                  type: "init",
                  rules: rules.hidden, //当前字段的隐藏规则
                  form_rules: tplData.form.form_rules, //当前表单的所有规则
                  form_data: tplData.calculateFormData, // tplData.form.form_data, //表单数据
                  callBack: function (rst_value) {
                    if (rst_value === true) cell.isHidden = rst_value; //给单元格绑定条件隐藏属性
                  },
                });

                hiddenRules.forEach((rule) => {
                  //注册规则
                  eventBus.subscribe(`rule.${rule}`, () => {

                    setRuleResult({
                      tb_code: "main", //所在分组code 主表为main
                      type: "init",
                      rules: rules.hidden, //当前字段的隐藏规则
                      form_rules: tplData.form.form_rules, //当前表单的所有规则
                      form_data: mergecalculateFormData(tplData), //表单数据
                      callBack: function (rst_value) {
                        if (cell.isHidden !== rst_value) {
                          //如果有变化就更新
                          cell.isHidden = rst_value; //给单元格绑定条件隐藏属性
                          eventBus.publish(`group.update.${group.id}`);
                        }
                      },
                    });
                  });
                });
              }

              //是否有必填规则
              let requiredRules = rules.required?.rules;
              if (requiredRules && requiredRules.length > 0) {
                setRuleResult({
                  tb_code: "main", //所在分组code 主表为main
                  type: "init",
                  rules: rules.required, //当前字段的必填规则
                  form_rules: tplData.form.form_rules, //当前表单的所有规则
                  form_data: tplData.calculateFormData, // tplData.form.form_data, //表单数据
                  callBack: function (rst_value) {
                    if (rst_value === true) cellData.isRequired = rst_value; //给单元格绑定条件隐藏属性
                  },
                });

                requiredRules.forEach((rule) => {
                  //注册规则
                  eventBus.subscribe(`rule.${rule}`, () => {
                    setRuleResult({
                      tb_code: "main", //所在分组code 主表为main
                      type: "init",
                      rules: rules.required, //当前字段的隐藏规则
                      form_rules: tplData.form.form_rules, //当前表单的所有规则
                      form_data: mergecalculateFormData(tplData), //表单数据
                      callBack: function (rst_value) {
                        if (cellData.isRequired !== rst_value) {
                          //如果有变化就更新
                          cellData.isRequired = rst_value; //给单元格绑定条件隐藏属性
                          eventBus.publish(`group.update.${group.id}`);
                        }
                      },
                    });
                  });
                });
              }

              if (rules.style?.length > 0) {
                //有样式规则需要应用
                //1.找到所有的content样式规则
                let allContentStyles = rules.style?.filter((s) => s.target === "content") || [];

                //如果有ContentStyle
                if (allContentStyles.length > 0) {
                  function applyContentRule(calculateFormData = tplData.calculateFormData) {
                    let hasContentStyle = false;
                    //之前的逻辑是把最后一个成功的规则Apply
                    for (let index = allContentStyles.length - 1; index >= 0; index--) {
                      if (hasContentStyle === true) break; //第一个满足条件的Apply样式规则
                      const element = allContentStyles[index];
                      setRuleResult({
                        tb_code: "main", //所在分组code 主表为main
                        type: "init",
                        rules: { rules: [element.id] }, //当前字段的样式规则
                        form_rules: tplData.form.form_rules, //当前表单的所有规则
                        form_data: calculateFormData, //表单数据
                        callBack: function (rst_value) {
                          if (rst_value === true) {
                            hasContentStyle = true;
                            cell.contentStyle = element.style; //给单元格绑定条件隐藏属性
                          }
                        },
                      });
                    }
                    if (hasContentStyle === false) {
                      cell.contentStyle = undefined;
                    }
                  }
                  applyContentRule();
                  //获取规则名称
                  const contentRules = [...new Set(allContentStyles.map((contentStyle) => contentStyle.id))];
                  contentRules.forEach((contentRule) => {
                    eventBus.subscribe(`rule.${contentRule}`, () => {
                      applyContentRule(mergecalculateFormData(tplData));
                      eventBus.publish(`group.update.${group.id}`);
                    });
                  });
                }

                //2. title样式

                let allTitleStyles = rules.style?.filter((s) => s.target === "title") || [];

                function applyTitleRule(calculateFormData = tplData.calculateFormData) {
                  let hasTitleStyle = false;
                  //之前的逻辑是把最后一个成功的规则Apply
                  for (let index = allTitleStyles.length - 1; index >= 0; index--) {
                    if (hasTitleStyle === true) break; //第一个满足条件的Apply样式规则
                    const element = allTitleStyles[index];
                    setRuleResult({
                      tb_code: "main", //所在分组code 主表为main
                      type: "init",
                      rules: { rules: [element.id] }, //当前字段的隐藏规则
                      form_rules: tplData.form.form_rules, //当前表单的所有规则
                      form_data: calculateFormData, //表单数据
                      callBack: function (rst_value) {
                        if (rst_value === true) {
                          hasTitleStyle = true;
                          cell.titleStyle = element.style; //给单元格绑定条件隐藏属性
                        }
                      },
                    });
                  }
                  if (hasTitleStyle === false) {
                    cell.titleStyle = undefined;
                  }
                }
                applyTitleRule();
                //获取规则名称
                const titleRules = [...new Set(allTitleStyles.map((titleStyle) => titleStyle.id))];
                titleRules.forEach((titleRule) => {
                  eventBus.subscribe(`rule.${titleRule}`, () => {
                    applyTitleRule(mergecalculateFormData(tplData));
                    eventBus.publish(`group.update.${group.id}`);
                  });
                });
              }
              //超链接隐藏
              let linkHideRules = cellData.designProps?.rules?.hiddenLink; //超链接隐藏条件
              if (linkHideRules) {
                function applyLinkRule(calculateFormData = tplData.calculateFormData) {
                  let hideResult = []; //当前超链接字段的所有隐藏结果
                  linkHideRules.map(function (linkHideRule, index) {
                    //遍历超链接条件
                    if (linkHideRule.linkName && hideResult.length !== undefined) {
                      //如果超链接条件存在linkName
                      hideResult = {}; //把hideResult转成对象
                    }

                    setRuleResult({
                      tb_code: "main", //所在分组code 主表为main
                      type: "init",
                      rules: linkHideRule.id, //当前字段的隐藏规则
                      form_rules: tplData.form.form_rules, //当前表单的所有规则
                      form_data: calculateFormData, //表单数据
                      callBack: function (rst_value) {
                        if (linkHideRule.linkName) {
                          //如果超链接条件存在linkName
                          hideResult[linkHideRule.linkName] = rst_value;
                        } else {
                          //兼容历史数据，没有linkName，直接存结果
                          hideResult.push(rst_value);
                        }
                      },
                    }); //设置列隐藏
                    cellData.linkHidden = hideResult; //超链接隐藏结果
                  });
                }

                applyLinkRule();
                //注册超链接隐藏事件
                linkHideRules.forEach((linkHideRule) => {
                  eventBus.subscribe(`rule.${linkHideRule.id}`, () => {
                    applyLinkRule(mergecalculateFormData(tplData));
                    eventBus.publish(`group.update.${group.id}`);
                  });
                });
              }
            }
          } else {
            //用来表示是否是空cell
            cell.isEmpty = true;
          }

        });
      });
    }
  });

  //主表计算字段注册计算事件
  tplData.form?.data_define?.main?.fields?.forEach((field) => {
    if (field?.type === "calculation" && tplData.view_mode !== true) {
      let code = field.code;
      //更新计算公式依赖的扩展方法
      var configs = field?.props?.functions;
      if (configs) {
        for (var funcName in configs) {
          let functionConfigPath = "functionConfigs." + funcName.toLowerCase();
          let hasSet = get(operator, functionConfigPath); //operator内是否已存在 funcName 的配置
          if (!hasSet) {
            //如果没有才进行一次添加
            var config = cloneDeep(configs[funcName]);
            set(operator, functionConfigPath, config); //更新当前计算字段的 apieval 公式到计算属性
          }
        }
      }
      var expression = field?.props?.expression;
      if (expression) {
        var isCalculate = getIscalculate(expression);
        let fieldPath = "form.form_data.main." + code;
        
        //1、初始化时，计算当前主表字段
        let needInitiateCal = canInitiateCal({
          tplData: tplData,
          field: field
        });//是否需要初始化计算
        if(needInitiateCal){
          mainCalculateValue({
            reloadCalculateFormData : 0,
            isCalculate: isCalculate,
            tplData,
            expression,
            fieldPath: fieldPath,
            code: code,
            field: field
          });
        }

        //其他字段change时，触发主表当前字段计算
        function doCalc(triggerField, value, index) {
          if (triggerField === fieldPath) return;
          if (triggerField.startsWith("form.form_data.children.")) {
            //触发字段是子表
            if (isCalculate === false) {//存在聚合函数
              let originField = triggerField.replace("form.form_data.", "").replace(/\[.*\]/, "");
              if (parser.contains(expression, originField)) {
                mainCalculateValue({
                  reloadCalculateFormData : this,
                  isCalculate: isCalculate,
                  tplData,
                  expression,
                  fieldPath: fieldPath,
                  code: code,
                  field: field
                });
              }
            }
          } else if (triggerField.startsWith("form.form_data.main.")) {
            //触发字段是主表
            let originField = triggerField.replace("form.form_data.", "");
            if (parser.contains(expression, originField)) {
              mainCalculateValue({
                reloadCalculateFormData : this,
                isCalculate: isCalculate,
                tplData,
                expression,
                fieldPath: fieldPath,
                code: code,
                field: field
              });
            }
          }
        }

        eventBus.subscribe("field.blur", doCalc.bind(1));
        eventBus.subscribe("field.triggerCalculate", doCalc);
      }
    }
  });

  //子表注册计算事件
  tplData.form?.data_define?.children?.forEach((group) => {
    //子表
    let subTableRows = tplData.form.form_data?.children?.[group.code];
    if(!subTableRows){//如果数据源里面没有包含子表数据，前端做兼容给一个默认的空数组
      subTableRows = [];
      set(tplData, "form.form_data.children." + group.code, subTableRows);
    }

    //1.字段绑定注册事件
    group?.fields.forEach((field) => {
      if (field?.type === "calculation" && tplData.view_mode !== true) {
        let code = field.code;
        //更新计算公式依赖的扩展方法
        var configs = field?.props?.functions;
        if (configs) {
          for (var funcName in configs) {
            let functionConfigPath = "functionConfigs." + funcName.toLowerCase();
            let hasSet = get(operator, functionConfigPath); //operator内是否已存在 funcName 的配置
            if (!hasSet) {
              //如果没有才进行一次添加
              var config = cloneDeep(configs[funcName]);
              set(operator, functionConfigPath, config); //更新当前计算字段的 apieval 公式到计算属性
            }
          }
        }
        var expression = field?.props?.expression;
        if (expression) {
          //1.初始化时，计算所有行的当前列
          let needInitiateCal = canInitiateCal({
            tplData: tplData,
            field: field
          });//是否需要初始化计算
          if(needInitiateCal){
            subtableCalculate({
              subTableRows: subTableRows,
              reloadCalculateFormData: 0,
              tplData: tplData,
              expression: expression,
              group: group,
              code: code,
              field: field
            })
          }

          //其他字段change，触发当前列计算
          function doCalc(triggerField, value, rowIndex) {
            if (triggerField.startsWith("form.form_data.children.")) {
              //1、触发字段是子表，值计算当前行
              let fieldPath = `form.form_data.children.${group.code}[${rowIndex}].${code}`;
                let originField = triggerField.replace("form.form_data.", "").replace(/\[.*\]/, "");
                if (parser.contains(expression, originField)) {
                  subCalculateValue({
                    reloadCalculateFormData: this,
                    tplData: tplData,
                    expression: expression,
                    group: group,
                    rowIndex: rowIndex,
                    fieldPath: fieldPath,
                    field: field
                  });
                }
            } else if (triggerField.startsWith("form.form_data.main.")) {
              //触发字段是主表，则计算所有行的当前列
              let originField = triggerField.replace("form.form_data.", "");
              if (parser.contains(expression, originField)) {
                subtableCalculate({
                  subTableRows: subTableRows,
                  reloadCalculateFormData: this,
                  tplData: tplData,
                  expression: expression,
                  group: group,
                  code: code,
                  field: field
                })
         
              }
            }
          }
      
          eventBus.subscribe("field.blur", doCalc.bind(1));
          eventBus.subscribe("field.triggerCalculate", doCalc);
        }
      }
    });

    //2.子表的行绑定监听事件，新增行时，把当前行的每个字段都计算一遍
    eventBus.subscribe("group.row.triggerCalculate."+group.code,(rowIndex)=>{

      group?.fields.forEach((field) => {
        if (field?.type === "calculation" && tplData.view_mode !== true) {

          var expression = field?.props?.expression;
          if (expression) {
            let code = field.code;
            subCalculateValue({
              reloadCalculateFormData: 1,
              tplData: tplData,
              expression: expression,
              group: group,
              rowIndex: rowIndex,
              fieldPath: `form.form_data.children.${group.code}[${rowIndex}].${code}`,
              field: field
            });
          }

        }})

    })

  });
}

//计算整个子表的字段
function subtableCalculate({
  subTableRows,
  reloadCalculateFormData,
  tplData,
  expression,
  group,
  code,
  field//当前需要计算的字段
}){
  subTableRows.forEach((row, rowIndex) => {
    subCalculateValue({
      reloadCalculateFormData: reloadCalculateFormData,
      tplData: tplData,
      expression: expression,
      group: group,
      rowIndex: rowIndex,
      fieldPath: `form.form_data.children.${group.code}[${rowIndex}].${code}`,
      field: field
    });
  });
}

//子表字段计算
function subCalculateValue({
  reloadCalculateFormData = 0,
  tplData,
  expression,
  group,
  rowIndex,
  fieldPath,
  field
}){
  
  if (reloadCalculateFormData === 1) {
    tplData.calculateFormData = mergecalculateFormData(tplData);
  }
  var rst_expression = parser.parse(expression, tplData.calculateFormData, { table_code: group.code, row_i: rowIndex });
  calculator.calculateAsync(rst_expression, function (rst_value) {
    if ((typeof rst_value === "number" && isNaN(rst_value)) || rst_value === false || (typeof rst_value === "string" && rst_value === "NaN")) rst_value = 0;
    
    rst_value = formatPrecision({
      field: field,
      rst_value: rst_value
    });//对计算结果进行小数位格式化

    if (get(tplData, fieldPath) !== rst_value) {
      set(tplData, fieldPath, rst_value);
      //更新calculateFormData
      if (tplData.calculateFormData) set(tplData.calculateFormData, fieldPath.replace("form.form_data.", ""), rst_value);
      eventBus.publishAsync("field.blur", fieldPath, rst_value, rowIndex);
      eventBus.publish(updateField + fieldPath, rst_value);
    }
  });
  
}

//主表字段计算
function mainCalculateValue({
  reloadCalculateFormData = 0,
  tplData,
  expression,
  fieldPath,
  code,
  field
}) {
  if (reloadCalculateFormData === 1) {
    tplData.calculateFormData = mergecalculateFormData(tplData);
  }
  var rst_expression = parser.parse(expression, tplData.calculateFormData);

  calculator.calculateAsync(rst_expression, function (rst_value) {

    rst_value = formatPrecision({
      field: field,
      rst_value: rst_value
    });//对计算结果进行小数位格式化

    if ((typeof rst_value === "number" && isNaN(rst_value)) || rst_value === false || (typeof rst_value === "string" && rst_value === "NaN")) rst_value = 0;
    if (get(tplData, fieldPath) !== rst_value) {
      set(tplData, fieldPath, rst_value);
      //更新calculateFormData
      if (tplData.calculateFormData) set(tplData.calculateFormData, "main." + code, rst_value);
      eventBus.publishAsync("field.blur", fieldPath, rst_value);
    }
    // updater();
    eventBus.publish(updateField + fieldPath, rst_value);
  });
}

//是否允许初始化计算
function canInitiateCal({
  tplData,
  field
}){
  var flowStatus = tplData.__flowStatus__;//当前流程状态
  var status = ["start", "restart"];//发起 重新发起

  //1.流程状态是 发起 重新发起
  if(~status.indexOf(flowStatus)) {
    return true;//返回true，初始化计算
  }

  //2.流程状态是 草稿
  //is_new_form 草稿对应的模板是否有被修改过
  //is_editable 字段步骤权限 true可编辑 false不可编辑
  /*
    前提条件，发起时保存草稿后
    情况1、草稿对应模板未被修改，is_new_form = false，这种情况不做初始化计算
    情况2、草稿对应模板被修改了，is_new_form = true，这种情况要做初始化计算
  */
  if(flowStatus === "draft" && tplData.form.is_new_form === true && field.is_editable !== true){//满足情况2 && 当前计算字段不可编辑
    return true;//返回true，初始化计算
  }

  return false;//其他情况不做初始化计算
}

//格式化小数位
function formatPrecision({
  field,//当前的计算字段
  rst_value//计算返回的结果
}){
  let precision = 4;//需要格式化的小数位默认为6位，防止出现科学计数法

  //计算字段是数值类型 || 没有show_type属性时（历史数据没有），默认把计算字段当数值类型处理，需要对计算结果做格式化处理
  if(field?.show_type === "number" || field?.show_type === undefined){
    
    if(field?.show_type === "number"){//如果是数值类型，没数值类型
      /*
        如果计算出来的结果是 0.1234
        配置的小数位是精度是2，则小数位对结果进行四舍五入为 -> 0.12
        如果配置了百分比，则显示值为12.00%
        精度是操作原始值，不操作显示值
      */
      precision = field?.props?.precision;//取配置的小数位属性
      if(precision === undefined){
        precision = 4;//防止属性丢失
      }
    }
    
    rst_value = formatNumber(rst_value, {
      precision: precision//小数位
    });//返回带小数的数字字符串  比如 "0.1200"
    var reg = /^[-+]?(([0-9]+)([.]([0-9]+))?|([.]([0-9]+))?)$/;
    var pattern = new RegExp(reg);
    if (pattern.test(rst_value)) {//格式化后的值，是不是数值类型
      rst_value = Number(rst_value);//如果是数值类型，就转换成number类型，比如 "0.1200"会转换成0.12
    }
  }
  return rst_value;
}